{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": ""
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "1. 数据加载与预处理\n",
    "CIFAR-10 数据集包含 50000 张训练集和 10000 张测试集的彩色图片，每张图片的尺寸为 32x32x3，一共分为 10 类。我们将使用 torchvision.datasets 来加载 CIFAR-10 数据集。"
   ],
   "id": "d9d20332c3d6a467"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-10-14T17:19:23.308714Z",
     "start_time": "2024-10-14T17:19:19.245835Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import torchvision.transforms as transforms\n",
    "\n",
    "# 定义数据预处理（包括归一化）\n",
    "transform = transforms.Compose(\n",
    "    [transforms.ToTensor(),\n",
    "     transforms.Normalize((0.4914, 0.4822, 0.4465), (0.247, 0.243, 0.261))])\n",
    "\n",
    "# 加载 CIFAR-10 数据集\n",
    "trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)\n",
    "trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)\n",
    "\n",
    "testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)\n",
    "testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)\n",
    "\n",
    "classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')\n"
   ],
   "id": "85d16d8bfc07ac66",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Files already downloaded and verified\n",
      "Files already downloaded and verified\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "2. 网络模型设计\n",
    "模型1：包含5个卷积层和1个汇聚层的CNN\n",
    "\n",
    "我们设计一个卷积神经网络，包含以下层次：\n",
    "\n",
    "5 个卷积层\n",
    "1 个汇聚层\n",
    "全连接层用于分类"
   ],
   "id": "b9f380d77993952d"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-10-14T17:26:37.690231Z",
     "start_time": "2024-10-14T17:26:37.677231Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class CNN_Model1(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(CNN_Model1, self).__init__()\n",
    "        # 定义卷积层和汇聚层\n",
    "        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)  # 输出: (32, 32, 32)\n",
    "        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)  # 输出: (64, 32, 32)\n",
    "        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)  # 输出: (128, 32, 32)\n",
    "        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1)  # 输出: (256, 32, 32)\n",
    "        self.conv5 = nn.Conv2d(256, 512, kernel_size=3, padding=1)  # 输出: (512, 32, 32)\n",
    "        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)  # 汇聚层： (512, 16, 16)\n",
    "        \n",
    "        # 计算展平后的特征数量：512 * 16 * 16 = 131072\n",
    "        self.fc1 = nn.Linear(512 * 16 * 16, 512)  # 全连接层\n",
    "        self.fc2 = nn.Linear(512, 10)  # 输出层\n",
    "\n",
    "    def forward(self, x):\n",
    "        # 经过卷积和激活函数\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = F.relu(self.conv3(x))\n",
    "        x = F.relu(self.conv4(x))\n",
    "        x = self.pool(F.relu(self.conv5(x)))  # 汇聚层\n",
    "        # 确保展平成一维\n",
    "        x = x.view(x.size(0), -1)  # 展平为 (batch_size, 512 * 16 * 16)\n",
    "        # 全连接层\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "\n"
   ],
   "id": "f9c97c636ea6d103",
   "outputs": [],
   "execution_count": 7
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "模型2：包含10个卷积层和1个汇聚层的CNN\n",
    "\n",
    "这个网络增加了更多的卷积层，以增强模型的表达能力：\n",
    "\n",
    "10 个卷积层\n",
    "1 个汇聚层\n",
    "全连接层用于分类"
   ],
   "id": "2d5c5aa7f7f7baa3"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-10-14T17:26:32.947130Z",
     "start_time": "2024-10-14T17:26:32.925929Z"
    }
   },
   "cell_type": "code",
   "source": [
    "class CNN_Model2(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(CNN_Model2, self).__init__()\n",
    "        self.conv1 = nn.Conv2d(3, 32, kernel_size=3, padding=1)\n",
    "        self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)\n",
    "        self.conv3 = nn.Conv2d(64, 128, kernel_size=3, padding=1)\n",
    "        self.conv4 = nn.Conv2d(128, 256, kernel_size=3, padding=1)\n",
    "        self.conv5 = nn.Conv2d(256, 512, kernel_size=3, padding=1)\n",
    "        self.conv6 = nn.Conv2d(512, 512, kernel_size=3, padding=1)\n",
    "        self.conv7 = nn.Conv2d(512, 512, kernel_size=3, padding=1)\n",
    "        self.conv8 = nn.Conv2d(512, 512, kernel_size=3, padding=1)\n",
    "        self.conv9 = nn.Conv2d(512, 512, kernel_size=3, padding=1)\n",
    "        self.conv10 = nn.Conv2d(512, 512, kernel_size=3, padding=1)\n",
    "        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n",
    "        \n",
    "        # 计算展平后的特征数量：512 * 16 * 16\n",
    "        self.fc1 = nn.Linear(512 * 16 * 16, 512)\n",
    "        self.fc2 = nn.Linear(512, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = F.relu(self.conv1(x))\n",
    "        x = F.relu(self.conv2(x))\n",
    "        x = F.relu(self.conv3(x))\n",
    "        x = F.relu(self.conv4(x))\n",
    "        x = F.relu(self.conv5(x))\n",
    "        x = self.pool(F.relu(self.conv6(x)))  # 汇聚层\n",
    "        x = F.relu(self.conv7(x))\n",
    "        x = F.relu(self.conv8(x))\n",
    "        x = F.relu(self.conv9(x))\n",
    "        x = F.relu(self.conv10(x))\n",
    "        x = x.view(x.size(0), -1)  # 展平为 (batch_size, 512 * 16 * 16)\n",
    "        x = F.relu(self.fc1(x))\n",
    "        x = self.fc2(x)\n",
    "        return x\n",
    "\n"
   ],
   "id": "7694c09886719ff7",
   "outputs": [],
   "execution_count": 6
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "3. 模型训练与评估\n",
    "我们定义损失函数、优化器，并训练模型。"
   ],
   "id": "6041c48c4c6af3a5"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-10-14T17:26:45.333005Z",
     "start_time": "2024-10-14T17:26:45.319007Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch.optim as optim\n",
    "\n",
    "# 定义损失函数和优化器\n",
    "def train_model(model, trainloader, testloader, =10):\n",
    "    criterion = nn.CrossEntropyLoss()\n",
    "    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)\n",
    "    \n",
    "    for epoch in range(epochs):  # 训练多个 epoch\n",
    "        running_loss = 0.0\n",
    "        for i, data in enumerate(trainloader, 0):\n",
    "            inputs, labels = data\n",
    "\n",
    "            # 前向传播 + 反向传播 + 优化\n",
    "            optimizer.zero_grad()\n",
    "            outputs = model(inputs)\n",
    "            loss = criterion(outputs, labels)\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "\n",
    "            running_loss += loss.item()\n",
    "            if i % 100 == 99:    # 每100个mini-batches打印一次\n",
    "                print(f'[Epoch {epoch + 1}, Batch {i + 1}] loss: {running_loss / 100:.3f}')\n",
    "                running_loss = 0.0\n",
    "\n",
    "    print('Finished Training')\n",
    "\n",
    "# 评估模型准确率\n",
    "def evaluate_model(model, testloader):\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    with torch.no_grad():\n",
    "        for data in testloader:\n",
    "            images, labels = data\n",
    "            outputs = model(images)\n",
    "            _, predicted = torch.max(outputs, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "\n",
    "    print(f'Accuracy: {100 * correct / total:.2f}%')\n"
   ],
   "id": "cf7af576d6a814f1",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "1. 性能对比实验代码\n",
    "首先，我们定义代码来训练和评估两个模型，并记录它们的损失和准确率。"
   ],
   "id": "d46d3214d5a9ad95"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-10-14T17:46:03.486455Z",
     "start_time": "2024-10-14T17:26:53.131605Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 训练并记录损失和准确率\n",
    "def train_and_evaluate(model, trainloader, testloader, epochs=10):\n",
    "    criterion = nn.CrossEntropyLoss()\n",
    "    optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)\n",
    "    \n",
    "    train_losses = []\n",
    "    test_accuracies = []\n",
    "    \n",
    "    for epoch in range(epochs):\n",
    "        model.train()\n",
    "        running_loss = 0.0\n",
    "        for i, data in enumerate(trainloader, 0):\n",
    "            inputs, labels = data\n",
    "\n",
    "            optimizer.zero_grad()  # 清空梯度\n",
    "            outputs = model(inputs)  # 前向传播\n",
    "            loss = criterion(outputs, labels)  # 计算损失\n",
    "            loss.backward()  # 反向传播\n",
    "            optimizer.step()  # 优化\n",
    "\n",
    "            running_loss += loss.item()\n",
    "\n",
    "        # 记录每个 epoch 的平均训练损失\n",
    "        train_losses.append(running_loss / len(trainloader))\n",
    "        \n",
    "        # 评估在测试集上的准确率\n",
    "        model.eval()\n",
    "        correct = 0\n",
    "        total = 0\n",
    "        with torch.no_grad():\n",
    "            for data in testloader:\n",
    "                images, labels = data\n",
    "                outputs = model(images)\n",
    "                _, predicted = torch.max(outputs, 1)\n",
    "                total += labels.size(0)\n",
    "                correct += (predicted == labels).sum().item()\n",
    "        \n",
    "        accuracy = 100 * correct / total\n",
    "        test_accuracies.append(accuracy)\n",
    "        print(f'Epoch {epoch+1}/{epochs}, Loss: {running_loss / len(trainloader):.4f}, Accuracy: {accuracy:.2f}%')\n",
    "\n",
    "    return train_losses, test_accuracies\n",
    "\n",
    "# 训练和评估模型1\n",
    "model1 = CNN_Model1()\n",
    "train_losses_model1, test_accuracies_model1 = train_and_evaluate(model1, trainloader, testloader, epochs=10)\n",
    "\n",
    "# 训练和评估模型2\n",
    "model2 = CNN_Model2()\n",
    "train_losses_model2, test_accuracies_model2 = train_and_evaluate(model2, trainloader, testloader, epochs=10)\n"
   ],
   "id": "900ea9fa758e8ffe",
   "outputs": [
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mKeyboardInterrupt\u001B[0m                         Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[9], line 48\u001B[0m\n\u001B[0;32m     46\u001B[0m \u001B[38;5;66;03m# 训练和评估模型1\u001B[39;00m\n\u001B[0;32m     47\u001B[0m model1 \u001B[38;5;241m=\u001B[39m CNN_Model1()\n\u001B[1;32m---> 48\u001B[0m train_losses_model1, test_accuracies_model1 \u001B[38;5;241m=\u001B[39m \u001B[43mtrain_and_evaluate\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmodel1\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtrainloader\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mtestloader\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mepochs\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;241;43m10\u001B[39;49m\u001B[43m)\u001B[49m\n\u001B[0;32m     50\u001B[0m \u001B[38;5;66;03m# 训练和评估模型2\u001B[39;00m\n\u001B[0;32m     51\u001B[0m model2 \u001B[38;5;241m=\u001B[39m CNN_Model2()\n",
      "Cell \u001B[1;32mIn[9], line 35\u001B[0m, in \u001B[0;36mtrain_and_evaluate\u001B[1;34m(model, trainloader, testloader, epochs)\u001B[0m\n\u001B[0;32m     33\u001B[0m \u001B[38;5;28;01mfor\u001B[39;00m data \u001B[38;5;129;01min\u001B[39;00m testloader:\n\u001B[0;32m     34\u001B[0m     images, labels \u001B[38;5;241m=\u001B[39m data\n\u001B[1;32m---> 35\u001B[0m     outputs \u001B[38;5;241m=\u001B[39m \u001B[43mmodel\u001B[49m\u001B[43m(\u001B[49m\u001B[43mimages\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m     36\u001B[0m     _, predicted \u001B[38;5;241m=\u001B[39m torch\u001B[38;5;241m.\u001B[39mmax(outputs, \u001B[38;5;241m1\u001B[39m)\n\u001B[0;32m     37\u001B[0m     total \u001B[38;5;241m+\u001B[39m\u001B[38;5;241m=\u001B[39m labels\u001B[38;5;241m.\u001B[39msize(\u001B[38;5;241m0\u001B[39m)\n",
      "File \u001B[1;32m~\\miniconda3\\envs\\rgzn\\lib\\site-packages\\torch\\nn\\modules\\module.py:1553\u001B[0m, in \u001B[0;36mModule._wrapped_call_impl\u001B[1;34m(self, *args, **kwargs)\u001B[0m\n\u001B[0;32m   1551\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_compiled_call_impl(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)  \u001B[38;5;66;03m# type: ignore[misc]\u001B[39;00m\n\u001B[0;32m   1552\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m-> 1553\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_call_impl\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n",
      "File \u001B[1;32m~\\miniconda3\\envs\\rgzn\\lib\\site-packages\\torch\\nn\\modules\\module.py:1562\u001B[0m, in \u001B[0;36mModule._call_impl\u001B[1;34m(self, *args, **kwargs)\u001B[0m\n\u001B[0;32m   1557\u001B[0m \u001B[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001B[39;00m\n\u001B[0;32m   1558\u001B[0m \u001B[38;5;66;03m# this function, and just call forward.\u001B[39;00m\n\u001B[0;32m   1559\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m (\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_pre_hooks\n\u001B[0;32m   1560\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_backward_hooks\n\u001B[0;32m   1561\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_forward_pre_hooks):\n\u001B[1;32m-> 1562\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mforward_call\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m   1564\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m   1565\u001B[0m     result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n",
      "Cell \u001B[1;32mIn[7], line 25\u001B[0m, in \u001B[0;36mCNN_Model1.forward\u001B[1;34m(self, x)\u001B[0m\n\u001B[0;32m     23\u001B[0m x \u001B[38;5;241m=\u001B[39m F\u001B[38;5;241m.\u001B[39mrelu(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mconv3(x))\n\u001B[0;32m     24\u001B[0m x \u001B[38;5;241m=\u001B[39m F\u001B[38;5;241m.\u001B[39mrelu(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mconv4(x))\n\u001B[1;32m---> 25\u001B[0m x \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mpool(F\u001B[38;5;241m.\u001B[39mrelu(\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mconv5\u001B[49m\u001B[43m(\u001B[49m\u001B[43mx\u001B[49m\u001B[43m)\u001B[49m))  \u001B[38;5;66;03m# 汇聚层\u001B[39;00m\n\u001B[0;32m     26\u001B[0m \u001B[38;5;66;03m# 确保展平成一维\u001B[39;00m\n\u001B[0;32m     27\u001B[0m x \u001B[38;5;241m=\u001B[39m x\u001B[38;5;241m.\u001B[39mview(x\u001B[38;5;241m.\u001B[39msize(\u001B[38;5;241m0\u001B[39m), \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m1\u001B[39m)  \u001B[38;5;66;03m# 展平为 (batch_size, 512 * 16 * 16)\u001B[39;00m\n",
      "File \u001B[1;32m~\\miniconda3\\envs\\rgzn\\lib\\site-packages\\torch\\nn\\modules\\module.py:1553\u001B[0m, in \u001B[0;36mModule._wrapped_call_impl\u001B[1;34m(self, *args, **kwargs)\u001B[0m\n\u001B[0;32m   1551\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_compiled_call_impl(\u001B[38;5;241m*\u001B[39margs, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs)  \u001B[38;5;66;03m# type: ignore[misc]\u001B[39;00m\n\u001B[0;32m   1552\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[1;32m-> 1553\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_call_impl\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n",
      "File \u001B[1;32m~\\miniconda3\\envs\\rgzn\\lib\\site-packages\\torch\\nn\\modules\\module.py:1562\u001B[0m, in \u001B[0;36mModule._call_impl\u001B[1;34m(self, *args, **kwargs)\u001B[0m\n\u001B[0;32m   1557\u001B[0m \u001B[38;5;66;03m# If we don't have any hooks, we want to skip the rest of the logic in\u001B[39;00m\n\u001B[0;32m   1558\u001B[0m \u001B[38;5;66;03m# this function, and just call forward.\u001B[39;00m\n\u001B[0;32m   1559\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m (\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_forward_pre_hooks\n\u001B[0;32m   1560\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_backward_pre_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_backward_hooks\n\u001B[0;32m   1561\u001B[0m         \u001B[38;5;129;01mor\u001B[39;00m _global_forward_hooks \u001B[38;5;129;01mor\u001B[39;00m _global_forward_pre_hooks):\n\u001B[1;32m-> 1562\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mforward_call\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43margs\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[0;32m   1564\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m   1565\u001B[0m     result \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;01mNone\u001B[39;00m\n",
      "File \u001B[1;32m~\\miniconda3\\envs\\rgzn\\lib\\site-packages\\torch\\nn\\modules\\conv.py:458\u001B[0m, in \u001B[0;36mConv2d.forward\u001B[1;34m(self, input)\u001B[0m\n\u001B[0;32m    457\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mforward\u001B[39m(\u001B[38;5;28mself\u001B[39m, \u001B[38;5;28minput\u001B[39m: Tensor) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m Tensor:\n\u001B[1;32m--> 458\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_conv_forward\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;28;43minput\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mweight\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mbias\u001B[49m\u001B[43m)\u001B[49m\n",
      "File \u001B[1;32m~\\miniconda3\\envs\\rgzn\\lib\\site-packages\\torch\\nn\\modules\\conv.py:454\u001B[0m, in \u001B[0;36mConv2d._conv_forward\u001B[1;34m(self, input, weight, bias)\u001B[0m\n\u001B[0;32m    450\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mpadding_mode \u001B[38;5;241m!=\u001B[39m \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mzeros\u001B[39m\u001B[38;5;124m'\u001B[39m:\n\u001B[0;32m    451\u001B[0m     \u001B[38;5;28;01mreturn\u001B[39;00m F\u001B[38;5;241m.\u001B[39mconv2d(F\u001B[38;5;241m.\u001B[39mpad(\u001B[38;5;28minput\u001B[39m, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_reversed_padding_repeated_twice, mode\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mpadding_mode),\n\u001B[0;32m    452\u001B[0m                     weight, bias, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mstride,\n\u001B[0;32m    453\u001B[0m                     _pair(\u001B[38;5;241m0\u001B[39m), \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mdilation, \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mgroups)\n\u001B[1;32m--> 454\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[43mF\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mconv2d\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;28;43minput\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mweight\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mbias\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mstride\u001B[49m\u001B[43m,\u001B[49m\n\u001B[0;32m    455\u001B[0m \u001B[43m                \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mpadding\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mdilation\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mgroups\u001B[49m\u001B[43m)\u001B[49m\n",
      "\u001B[1;31mKeyboardInterrupt\u001B[0m: "
     ]
    }
   ],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "2. 生成损失和准确率的对比图\n",
    "我们可以使用 matplotlib 绘制两个模型的训练损失和测试准确率的对比图，方便分析它们的性能差异。"
   ],
   "id": "7bfb40f8bab763b9"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": [
    "# 绘制训练损失的对比图\n",
    "def plot_loss_comparison(train_losses_model1, train_losses_model2):\n",
    "    plt.figure(figsize=(10,5))\n",
    "    plt.plot(train_losses_model1, label='Model 1 (5 Conv Layers)')\n",
    "    plt.plot(train_losses_model2, label='Model 2 (10 Conv Layers)')\n",
    "    plt.title('Training Loss Comparison')\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Loss')\n",
    "    plt.legend()\n",
    "    plt.show()\n",
    "\n",
    "# 绘制测试准确率的对比图\n",
    "def plot_accuracy_comparison(test_accuracies_model1, test_accuracies_model2):\n",
    "    plt.figure(figsize=(10,5))\n",
    "    plt.plot(test_accuracies_model1, label='Model 1 (5 Conv Layers)')\n",
    "    plt.plot(test_accuracies_model2, label='Model 2 (10 Conv Layers)')\n",
    "    plt.title('Test Accuracy Comparison')\n",
    "    plt.xlabel('Epoch')\n",
    "    plt.ylabel('Accuracy (%)')\n",
    "    plt.legend()\n",
    "    plt.show()\n",
    "\n",
    "# 绘制训练损失对比图\n",
    "plot_loss_comparison(train_losses_model1, train_losses_model2)\n",
    "\n",
    "# 绘制测试准确率对比图\n",
    "plot_accuracy_comparison(test_accuracies_model1, test_accuracies_model2)\n"
   ],
   "id": "1fb1941c51963206"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
